﻿using wwl.Domain.Entities.Common;

namespace wwl.Domain.Entities.Rbac
{
  /// <summary>
  /// 租户聚合根（DDD 核心领域实体）
  /// 属于权限模块（Rbac）的核心聚合根，承载租户相关的核心业务状态与领域规则
  /// 聚合边界：租户自身属性 + 其关联的子实体（如租户下的用户、角色，本示例简化为单实体聚合）
  /// </summary>
  public class Tenant : BaseEntity
  {
    /// <summary>
    /// 租户编码（领域核心业务标识）
    /// </summary>
    /// <remarks>
    /// 1. 遵循 DDD“领域实体业务唯一性”原则：租户编码是业务层面的唯一标识（区别于 Id 技术标识），用于业务场景识别（如租户登录、数据隔离）。
    /// 2. 业务规则内嵌：编码不可重复、不可为空，该规则通过领域服务或仓储接口（如 ITenantRepository.ExistsByCodeAsync）保障，体现 DDD“业务规则内聚于领域”思想。
    /// 3. 空字符串默认值：避免 null 导致的业务语义模糊，确保领域实体状态初始化完整，符合 DDD“实体自包含、状态一致”要求。
    /// </remarks>
    public string TenantCode { get; set; } = string.Empty;

    /// <summary>
    /// 租户名称（领域核心业务属性）
    /// </summary>
    /// <remarks>
    /// 1. 承载租户的核心业务描述，是领域层识别租户的关键属性，符合 DDD“实体属性围绕业务语义设计”原则。
    /// 2. 业务约束隐含：名称不可为空、长度有业务限制（如不超过50字符），该约束通过领域服务校验，确保实体状态符合业务规范。
    /// </remarks>
    public string TenantName { get; set; } = string.Empty;

    /// <summary>
    /// 租户状态（领域状态枚举，封装业务状态语义）
    /// </summary>
    /// <remarks>
    /// 1. 遵循 DDD“状态驱动业务行为”原则：状态枚举将“启用/禁用”的业务语义显性化，避免使用魔法值（如 0/1）导致的语义模糊。
    /// 2. 绑定领域规则：不同状态对应不同业务行为（如 ENABLED 状态可分配资源，DISABLED 状态不可登录），规则内嵌于领域服务（如 TenantService），体现 DDD“状态与行为绑定”思想。
    /// 3. 默认启用状态：符合业务常识（租户创建后默认可使用），确保实体初始化即具备合理业务状态，减少外部干预。
    /// </remarks>
    public TenantStatus Status { get; set; } = TenantStatus.ENABLED;

    /// <summary>
    /// 领域行为：启用租户（DDD 实体行为封装）
    /// </summary>
    /// <remarks>
    /// 遵循 DDD“实体行为承载业务逻辑”原则：将“启用租户”的业务操作封装为实体方法，而非外部服务，确保状态变更与业务规则统一。
    /// </remarks>
    public void Enable()
    {
      if (Status == TenantStatus.ENABLED)
      {
        throw new InvalidOperationException("租户已处于启用状态，无需重复操作");
      }
      Status = TenantStatus.ENABLED;
      UpdatedTime = DateTime.UtcNow; // 状态变更同步更新生命周期时间，保持实体状态一致性
    }

    /// <summary>
    /// 领域行为：禁用租户（DDD 实体行为封装）
    /// </summary>
    /// <param name="reason">禁用原因（补充领域上下文）</param>
    /// <remarks>
    /// 1. 业务规则内嵌：禁用时需记录上下文（原因），体现 DDD“实体承载完整业务上下文”思想。
    /// 2. 状态变更校验：避免重复禁用，确保业务操作的合理性，符合 DDD“实体自我保护”原则。
    /// </remarks>
    public void Disable(string reason)
    {
      if (Status == TenantStatus.DISABLED)
      {
        throw new InvalidOperationException("租户已处于禁用状态，无需重复操作");
      }
      Status = TenantStatus.DISABLED;
      Remarks = reason; // 复用基类备注属性存储禁用原因，无需新增字段，优化领域模型
      UpdatedTime = DateTime.UtcNow;
    }
  }

  /// <summary>
  /// 租户状态枚举（DDD 领域枚举，封装业务状态语义）
  /// </summary>
  /// <remarks>
  /// 遵循 DDD“领域枚举不暴露技术实现”原则：枚举值采用业务语义化命名（ENABLED/DISABLED），与数据库存储、前端展示解耦，仅聚焦业务含义。
  /// </remarks>
  public enum TenantStatus
  {
    /// <summary>启用状态：租户可正常使用系统功能</summary>
    ENABLED,
    /// <summary>禁用状态：租户不可登录、不可使用核心功能</summary>
    DISABLED
  }
}